// pages/reservation/personal.js
const app = getApp()
import api from '../../utils/api'

Page({
  data: {
    loading: false,
    currentYear: '',
    currentMonth: '',
    // 日期列表（7天）
    dateItems: [],
    selectedDate: '',

    // 时段
    timeslotOptions: [],
    selectedTimeslotIndex: -1,
    selectedTimeslotLabel: '',

    canProceed: false,
    // 预约提醒富文本内容
    reservation_notice: ''
  },

  // 统一日期格式为 YYYY-MM-DD
  normalizeDateStr(d) {
    if (!d) return ''
    if (/^\d{4}-\d{2}-\d{2}$/.test(d)) return d
    if (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(d)) {
      const [y, m, da] = d.split(/[\/\-]/)
      return `${y}-${String(m).padStart(2,'0')}-${String(da).padStart(2,'0')}`
    }
    if (/^\d{8}$/.test(d)) {
      return `${d.slice(0,4)}-${d.slice(4,6)}-${d.slice(6,8)}`
    }
    try {
      const dt = new Date(d)
      if (!isNaN(dt.getTime())) {
        const y = dt.getFullYear()
        const m = String(dt.getMonth()+1).padStart(2,'0')
        const da = String(dt.getDate()).padStart(2,'0')
        return `${y}-${m}-${da}`
      }
    } catch(e){}
    return String(d)
  },

  async onLoad() {
    // 需要登录
    const ok = await app.checkAuth()
    if (!ok) return

    this.initDates()
    // 先加载7天开闭馆排期，更新日期状态
    await this.loadSchedule7Days()
    // 启动时顺序遍历每日情况，模拟点击逐日请求并更新状态
    await this.simulateClicksForWeek()
    // 再加载选中日期的时段
    this.loadTimeSlots()

    // 获取预约提醒等配置项
    this.get_museum_config();
  },

  onShow() {},

  // 初始化未来7天日期
  initDates() {
    const today = new Date()
    const year = today.getFullYear()
    const month = today.getMonth() + 1
    this.setData({
      currentYear: year,
      currentMonth: (month < 10 ? '0' : '') + month
    })

    const weekMap = ['周日','周一','周二','周三','周四','周五','周六']
    const list = []
    for (let i = 0; i < 7; i++) {
      const d = new Date()
      d.setDate(today.getDate() + i)
      const yyyy = d.getFullYear()
      const mm = (d.getMonth() + 1).toString().padStart(2, '0')
      const dd = d.getDate().toString().padStart(2, '0')
      const weekday = weekMap[d.getDay()]

      list.push({
        date: `${yyyy}-${mm}-${dd}`,
        day: dd,
        weekday: i === 0 ? '今天' : weekday,
        statusText: '可预约',
        statusClass: 'ok',
        disabled: false,
        selected: i === 0
      })
    }

    this.setData({
      dateItems: list,
      selectedDate: list[0].date
    })
  },

  // 新增：加载7天开闭馆排期并更新日期状态
  async loadSchedule7Days() {
    try {
      const list = this.data.dateItems || []
      if (!list.length) return
      const startDate = list[0].date
      const res = await api.reservation.getSchedule7Days(startDate, 7)
      // 兼容不同返回结构，尽量提取数组
      let arr = []
      if (Array.isArray(res)) arr = res
      else if (Array.isArray(res.days)) arr = res.days
      else if (Array.isArray(res.list)) arr = res.list
      else if (Array.isArray(res.items)) arr = res.items
      else if (Array.isArray(res.data)) arr = res.data

      // 构建日期->是否闭馆映射（使用标准化日期键）
      const map = {}
      ;(arr || []).forEach(it => {
        const raw = it.date || it.day || it.dt || it.date_str
        const d = this.normalizeDateStr(raw)
        if (!d) return
        const isClosed = it.is_closed === true || it.closed === true || it.open === false || it.status === 'closed' || it.status === '不开放' || it.status_text === '不开放'
        const reason = it.closure_reason || it.reason || ''
        map[d] = { isClosed, reason }
      })

      const updated = list.map(src => {
        const it = { ...src }
        const info = map[this.normalizeDateStr(it.date)]
        if (info) {
          if (info.isClosed) {
            it.statusText = '不开放'
            it.statusClass = 'closed'
            it.disabled = true
          } else {
            it.statusText = '可预约'
            it.statusClass = 'ok'
            it.disabled = false
          }
        }
        return it
      })

      this.setData({ dateItems: updated })
    } catch (e) {
      console.warn('获取7天开闭馆排期失败', e)
    }
  },

  // 新增：预加载未来7天的余量，标记“已约满”
  async preloadWeekAvailability() {
    try {
      const list = this.data.dateItems || []
      if (!list.length) return
      // 排除已闭馆的日期，避免不必要请求
      const datesToCheck = list.filter(it => it.statusClass !== 'closed').map(it => it.date)
      if (!datesToCheck.length) return

      // 并发请求7天的时段余量（保留请求日期，便于回退）
      const tasks = datesToCheck.map(d => api.reservation.getTimeSlots(d)
        .then(data => ({ ok: true, data, reqDate: d }))
        .catch(err => ({ ok: false, err, reqDate: d })))
      const results = await Promise.all(tasks)

      // 根据返回计算每一天是否“已约满”（使用标准化日期键+请求日期回退）
      const availabilityMap = {}
      results.forEach(r => {
        if (!r.ok || !r.data) {
          // 即使失败，也占位，避免后续二次请求造成闪烁
          const key = this.normalizeDateStr(r.reqDate)
          if (key) availabilityMap[key] = availabilityMap[key] || { totalAvailable: 0, isClosed: false }
          return
        }
        const data = r.data
        const key = this.normalizeDateStr(data.date) || this.normalizeDateStr(r.reqDate)
        const totalAvailable = (data.timeslots || []).reduce((s, x) => s + (x.available_count || 0), 0)
        const isClosed = !!data.is_closed
        if (key) availabilityMap[key] = { totalAvailable, isClosed }
      })

      const updated = (this.data.dateItems || []).map(src => {
        const it = { ...src }
        const info = availabilityMap[this.normalizeDateStr(it.date)]
        if (!info) return it
        if (info.isClosed) {
          it.statusText = '不开放'
          it.statusClass = 'closed'
          it.disabled = true
        } else if (info.totalAvailable <= 0) {
          it.statusText = '已约满'
          it.statusClass = 'full'
          it.disabled = true
        } else {
          it.statusText = '可预约'
          it.statusClass = 'ok'
          it.disabled = false
        }
        return it
      })

      this.setData({ dateItems: updated })
    } catch (e) {
      console.warn('预加载7天余量失败', e)
    }
  },

  // 新增：启动时顺序遍历每日情况，模拟点击逐个请求以确保状态准确
  async simulateClicksForWeek() {
    try {
      const list = this.data.dateItems || []
      if (!list.length) return
      // 依次请求，避免并发导致后端限流或混淆
      for (let i = 0; i < list.length; i++) {
        const item = this.data.dateItems[i]
        if (!item) continue
        // 已明确闭馆的日期无需再请求
        if (item.statusClass === 'closed') continue
        const reqDate = item.date
        let data = null
        try {
          data = await api.reservation.getTimeSlots(reqDate)
        } catch (e) {
          // 请求失败则跳过，但保留当前状态
          continue
        }
        // 计算状态
        const isClosed = !!(data && data.is_closed)
        const totalAvailable = (data && Array.isArray(data.timeslots)) ? data.timeslots.reduce((s, x) => s + (x.available_count || 0), 0) : 0

        // 更新对应 index 的日期项，逐次 setData 让 UI 逐步呈现
        const dateItems = this.data.dateItems.map((d, idx) => {
          if (idx !== i) return d
          const it = { ...d }
          if (isClosed) {
            it.statusText = '不开放'
            it.statusClass = 'closed'
            it.disabled = true
          } else if (totalAvailable <= 0) {
            it.statusText = '已约满'
            it.statusClass = 'full'
            it.disabled = true
          } else {
            it.statusText = '可预约'
            it.statusClass = 'ok'
            it.disabled = false
          }
          return it
        })
        this.setData({ dateItems })
        // 让渲染有时间完成，避免 UI 阻塞
        await new Promise(res => setTimeout(res, 30))
      }
    } catch (e) {
      console.warn('simulateClicksForWeek 执行失败', e)
    }
  },

  // 选择日期
  onSelectDate(e) {
    const idx = e.currentTarget.dataset.index
    const list = this.data.dateItems.map((it, i) => ({ ...it, selected: i === idx }))
    // 禁止选择已禁用日期
    if (list[idx].disabled) return
    const date = list[idx].date
    this.setData({ dateItems: list, selectedDate: date, selectedTimeslotIndex: -1, selectedTimeslotLabel: '', canProceed: false })
    this.loadTimeSlots()
  },

  // 加载时段
  async loadTimeSlots() {
    try {
      // 原有方法会造成页面闪烁，关闭掉
      // this.setData({ loading: true, timeslotOptions: [] })
      this.setData({ timeslotOptions: [] })
      const data = await api.reservation.getTimeSlots(this.data.selectedDate)
      // data.timeslots 数组
      const options = (data.timeslots || []).map(slot => ({
        value: slot.id,
        label: `${slot.name} ${slot.start_time}-${slot.end_time}（剩${slot.available_count}）`,
        raw: slot
      }))

      // 更新顶部日期状态（闭馆/可预约/已约满）
      const normRespDate = this.normalizeDateStr(data.date)
      const dateItems = this.data.dateItems.map(src => {
        const it = { ...src }
        if (this.normalizeDateStr(it.date) === normRespDate) {
          if (data.is_closed) {
            it.statusText = '不开放'
            it.statusClass = 'closed'
            it.disabled = true
          } else {
            // 按剩余名额判断
            const totalAvailable = (data.timeslots || []).reduce((s, x) => s + (x.available_count || 0), 0)
            if (totalAvailable <= 0) {
              it.statusText = '已约满'
              it.statusClass = 'full'
              it.disabled = true
            } else {
              it.statusText = '可预约'
              it.statusClass = 'ok'
              it.disabled = false
            }
          }
        }
        return it
      })

      this.setData({ timeslotOptions: options, dateItems, loading: false })
    } catch (err) {
      console.error('获取时段失败', err)
      this.setData({ loading: false })
      wx.showToast({ title: err.message || '加载失败', icon: 'none' })
    }
  },

  onTimeslotChange(e) {
    const idx = e.detail.value
    const option = this.data.timeslotOptions[idx]
    this.setData({ selectedTimeslotIndex: idx, selectedTimeslotLabel: option ? option.label : '', canProceed: !!option })
  },

  // 获取配置项
  async get_museum_config() {
    const data = await api.museum_config.getList()
    if (data.reservation_notice) {
      this.setData({ reservation_notice: data.reservation_notice.config_value })
    }
  },

  onNext() {
    if (!this.data.selectedDate) {
      wx.showToast({ title: '请先选择日期', icon: 'none' })
      return
    }
    if (!this.data.timeslotOptions.length || this.data.selectedTimeslotIndex < 0) {
      wx.showToast({ title: '请先选择时段', icon: 'none' })
      return
    }

    const slot = this.data.timeslotOptions[this.data.selectedTimeslotIndex]
    try { wx.setStorageSync('selected_slot', slot.raw) } catch(e){}
    const query = `?date=${this.data.selectedDate}&time_slot_id=${slot.value}`
    wx.navigateTo({ url: `/pages/reservation/personal_form${query}` })
  }
})